﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Swoosh.Contracts.MediaPlayerLib;
using System.Xml.Serialization;
using Swoosh.Utilities.TraceLogger;
using System.IO;
using System.Net;
using System.Globalization;
using System.Xml;

namespace Swoosh.MediaPlayers.WinampAjaxAmpV3
{
    public class Player : IPlaybackDevice
    {

        private string _Name;
        public string Name
        {
            get { return _Name; }
            set { _Name = value; }
        }

        private string _StorageName;
        public string StorageName
        {
            get { return _StorageName; }
            set { _StorageName = value; }
        }

        public Storage Storage
        {
            get
            {
                return SwooshConfig.CurrentConfig.StorageList.Where(s => s.Name == StorageName).FirstOrDefault();
            }
        }

        private Playlist _Playlist;
        public Playlist Playlist
        {
            get { return _Playlist; }
        }

        private WinampAjaxAmpV3Config _Config;

        public bool ClearPlaylist()
        {
            string requesturi = "http://" + _Config.ServerName + ":" + _Config.ServerPort + "/clearplaylist";
            int i = Int32.Parse(Encoding.UTF8.GetString(new WebClient().DownloadData(requesturi)));
            //returns 1 if successful
            return (i == 1);
        }

        public bool QueuePlaylistItem(PlaylistItem Item)
        {
            int result = 0;

            string filename = Item.File.Replace("\\", "/");
            string label = Uri.EscapeDataString(Item.Label);

            //string str = filename;
            //str = Uri.EscapeDataString(str.Replace("!", "%21").Replace("'", "%27").Replace("*", "%2A").Replace("\\", "\\\\"));

            string requesturi = "http://" + _Config.ServerName + ":" + _Config.ServerPort + "/enqueuefile" + "?filename=" + Item.File + "&title=" + label;

            WebClient web_client = new WebClient();

            Byte[] page_in_bytes = web_client.DownloadData(requesturi);

            result = Int32.Parse(Encoding.UTF8.GetString(page_in_bytes));

            return (result == 1);
        }

        public bool PlayPlaylistItem(PlaylistItem Item)
        {
            string requesturi = "http://" + _Config.ServerName + ":" + _Config.ServerPort + "/setplaylistpos" + "?=&index=" + Item.Position;
            WebClient web_client = new WebClient();
            Byte[] page_in_bytes = web_client.DownloadData(requesturi);
            int i = Int32.Parse(Encoding.UTF8.GetString(page_in_bytes)); //returns 1 if successful

            if (i == 1)
            // playlistposition was found
            {

                requesturi = "http://" + _Config.ServerName + ":" + _Config.ServerPort + "/play";
                page_in_bytes = web_client.DownloadData(requesturi);
                i = Int32.Parse(Encoding.UTF8.GetString(page_in_bytes)); //returns 1 if successful


                if (Item.SeekTime > 0)
                //seek to correct playback position
                {
                    //calculate pos in percent

                    //1. read out the length of the actual track
                    requesturi = "http://" + _Config.ServerName + ":" + _Config.ServerPort + "/consolestatus.xml";

                    string page_source = Encoding.UTF8.GetString(web_client.DownloadData(requesturi));

                    XmlDocument xmldoc = new XmlDocument();
                    xmldoc.LoadXml(page_source);

                    //read out the complete length of the track in ms

                    foreach (XmlNode node in xmldoc.GetElementsByTagName("lengthms"))
                    {
                        try
                        {
                            int length = Int32.Parse(node.InnerText);

                            //pos must be percentual, for example pos = 0.4 for 40% of the complete song
                            double pos = (double)Item.SeekTime * 1000 / (double)length;

                            requesturi = "http://" + _Config.ServerName + ":" + _Config.ServerPort + "/setposition?=&pos=" + pos.ToString(CultureInfo.InvariantCulture);
                            page_in_bytes = web_client.DownloadData(requesturi);
                            i = Int32.Parse(Encoding.UTF8.GetString(page_in_bytes)); //returns 1 if successful
                            return (i == 1);
                        }
                        catch
                        {

                        }
                    }
                    return (i == 1);
                }
            }
            return false;
        }

        public Playlist ReadPlayList()
        {
            string requesturi = "http://" + _Config.ServerName + ":" + _Config.ServerPort + "/playlist.xml";
            WebClient web_client = new WebClient();
            Byte[] page_in_bytes = web_client.DownloadData(requesturi);
            string page_source = Encoding.UTF8.GetString(page_in_bytes);

            XmlDocument xmldoc = new XmlDocument();
            xmldoc.LoadXml(page_source);

            _Playlist = new Playlist();

            //get the position of the current playlist item
            int current = GetCurrent();

            //read out the parameters for each playlist item and add it to _Playlist
            foreach (XmlNode node in xmldoc.GetElementsByTagName("track"))
            {
                string file = node["filename"].InnerText;
                string label = node["title"].InnerText;
                int position = Int32.Parse(node["index"].InnerText);
                bool isCurrent = (current == position);
                PlaylistItem pli = new PlaylistItem() { File = file, Label = label, Position = position, IsCurrent = isCurrent };

                if (isCurrent)
                {
                    _Playlist.Current = pli;
                }

                _Playlist.Items.Add(pli);

                Logger.Log(LogLevels.Debug, "Pos: " + position + " File: " + file);
            }


            if (_Playlist.Current != null)
            {
                double pos = GetProgressPosition();
                if (pos > 0)
                {
                    requesturi = "http://" + _Config.ServerName + ":" + _Config.ServerPort + "/consolestatus.xml";
                    web_client = new WebClient();
                    page_in_bytes = web_client.DownloadData(requesturi);
                    page_source = Encoding.UTF8.GetString(page_in_bytes);
                    xmldoc = new XmlDocument();
                    xmldoc.LoadXml(page_source);

                    foreach (XmlNode node in xmldoc.GetElementsByTagName("lengthms"))
                    {
                        pos *= Convert.ToDouble(node.InnerText)/1000;
                        _Playlist.Current.SeekTime = (int)pos;
                    }
                }
                else
                    _Playlist.Current.SeekTime = 0;

            }
            return _Playlist;
        }

        public bool StopPlayback()
        {
            string requesturi = "http://" + _Config.ServerName + ":" + _Config.ServerPort + "/stop";

            int i = Int32.Parse(Encoding.UTF8.GetString(new WebClient().DownloadData(requesturi)));

            return (i == 1);
        }

        private int GetCurrent()
        {
            string requesturi = "http://" + _Config.ServerName + ":" + _Config.ServerPort + "/getplaylistpos";

            int i = Int32.Parse(Encoding.UTF8.GetString(new WebClient().DownloadData(requesturi)));

            if (i > 0)
                return i;
            else
                return 0;
        }


        private double GetProgressPosition()
        {
            string pos = Encoding.UTF8.GetString(new WebClient().DownloadData("http://" + _Config.ServerName + ":" + _Config.ServerPort + "/getposition"));

            double d = Double.Parse(pos, CultureInfo.GetCultureInfo("en-US").NumberFormat);

            if (d > 0)
                return d;
            else
                return 0;
        }

        public bool LoadConfiguration(string Configuration)
        {
            bool ret = false;

            XmlSerializer xmlSer = new XmlSerializer(typeof(WinampAjaxAmpV3Config));

            try
            {
                _Config = (WinampAjaxAmpV3Config)xmlSer.Deserialize(new StringReader(Configuration));

                ret = true;
            }
            catch (Exception ex)
            {
                Logger.Log(LogLevels.Error, Name + " - unable to load configuration", ex);
                _Config = new WinampAjaxAmpV3Config();
            }
            return ret;
        }



        public bool Start()
        {
            return true;
        }

        public bool Stop()
        {
            return true;
        }
    }

}
